package com.ruoyi.project.determination.algorithm;

import com.ruoyi.project.determination.pojo.AssignmentResults;
import org.apache.commons.math3.optim.MaxIter;
import org.apache.commons.math3.optim.PointValuePair;
import org.apache.commons.math3.optim.linear.*;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;

import java.util.*;

public class Optimized_GRA {

    public AssignmentResults compute(double[][] costMatrix, int[] demandVector, int[][] supplyLimitMatrix, int[] maxDemand, double storageCost, List<String> productEnterprises, String product) {
        int numEnterprises = costMatrix.length;  // 企业数量
        int numMonths = costMatrix[0].length;  // 月份数量

        // 决策变量的系数矩阵
        double[] objectiveCoefficients = new double[numEnterprises * numMonths * 2];  // 包含 Tcon 和 Tadv
        int idx = 0;

        // 构建目标函数
        for (int i = 0; i < numEnterprises; i++) {
            for (int j = 0; j < numMonths; j++) {
                // Q[i,j] * T[i,j]
                objectiveCoefficients[idx++] = costMatrix[i][j];
                objectiveCoefficients[idx++] = costMatrix[i][j];  // Tcon 和 Tadv 的系数相同
            }
        }

        // 构建线性目标函数
        LinearObjectiveFunction objectiveFunction = new LinearObjectiveFunction(objectiveCoefficients, 0);

        // 添加约束条件
        List<LinearConstraint> constraints = new ArrayList<>();

        // 约束 (3.9) 和 (3.10): Tcon[i,j] 和 Tadv[i,j] 是非负整数，且 Tcon[i,j] + Tadv[i,j] <= La[i,j]
//        for (int i = 0; i < numEnterprises; i++) {
//            for (int j = 0; j < numMonths; j++) {
//                double[] sumCoefficients = new double[numEnterprises * numMonths * 2];
//                sumCoefficients[i * numMonths + j] = 1.0;  // Tcon[i,j]
//                sumCoefficients[numEnterprises * numMonths + i * numMonths + j] = 1.0;  // Tadv[i,j]
//                constraints.add(new LinearConstraint(sumCoefficients, Relationship.LEQ, supplyLimitMatrix[i][j]));
//                System.out.println("Total constraint for enterprise " + i + ", month " + j + ": " + Arrays.toString(sumCoefficients));
//            }
//        }
        for (int i = 0; i < numEnterprises; i++) {
            for (int j = 0; j < numMonths; j++) {
                double[] sumCoefficients = new double[numEnterprises * numMonths * 2];
                // Tcon[i,j] 的索引为 2 * (i * numMonths + j)
                sumCoefficients[2 * (i * numMonths + j)] = 1.0;  // Tcon[i,j]
                // Tadv[i,j] 的索引为 2 * (i * numMonths + j) + 1
                sumCoefficients[2 * (i * numMonths + j) + 1] = 1.0;  // Tadv[i,j]
                // 添加约束 Tcon[i,j] + Tadv[i,j] <= La[i,j]
                constraints.add(new LinearConstraint(sumCoefficients, Relationship.LEQ, supplyLimitMatrix[i][j]));
            }
        }

        // 约束 (3.11): sum(Tcon[i,j] + Reccon[i,j]) >= L[j]
        for (int j = 0; j < numMonths; j++) {
            double[] sumCoefficients = new double[numEnterprises * numMonths * 2];
            for (int i = 0; i < numEnterprises; i++) {
                sumCoefficients[i * numMonths + j] = 1.0;  // Tcon[i,j]

                // 添加递归消耗 Reccon[i,j] (前一个月的提前分配)
                if (j > 0) {
                    sumCoefficients[numEnterprises * numMonths + i * numMonths + (j - 1)] += 1.0;  // Reccon[i,j] 来自上一个月的 Tadv[i,j-1]
                }
            }
//            constraints.add(new LinearConstraint(sumCoefficients, Relationship.GEQ, demandVector[j]));
            constraints.add(new LinearConstraint(sumCoefficients, Relationship.EQ, demandVector[j]));
        }

        // 约束 (3.11): sum(Tcon[i,j]) + Reccon[i,j] >= L[j]
//        for (int j = 0; j < numMonths; j++) {
//            double[] sumCoefficients = new double[numEnterprises * numMonths * 2];
//
//            for (int i = 0; i < numEnterprises; i++) {
//                sumCoefficients[2 * (i * numMonths + j)] = 1.0;  // Tcon[i,j]
//
//                    // 添加递归消耗 Reccon[i,j] (前一个月的提前分配)
//                if (j > 0) {
//                    sumCoefficients[2 * (i * numMonths + (j - 1)) + 1] += 1.0;  // Reccon[i,j] 来自上一个月的 Tadv[i,j-1]
//                }
//            }
//
//            // 添加约束条件，确保sum(Tcon[i,j]) + Reccon[i,j] >= demandVector[j]
//            constraints.add(new LinearConstraint(sumCoefficients, Relationship.GEQ, demandVector[j]));
//        }


        // 约束 (3.12): Recsto[j] + sum(T[i,j]) <= U[j]
        for (int j = 0; j < numMonths; j++) {
            double[] sumCoefficients = new double[numEnterprises * numMonths * 2];
            for (int i = 0; i < numEnterprises; i++) {
                sumCoefficients[i * numMonths + j] = 1.0;  // Tcon[i,j]
                sumCoefficients[numEnterprises * numMonths + i * numMonths + j] = 1.0;  // Tadv[i,j]
            }

            // 添加递归存储 Recsto[j]，表示尚未消耗的提前分配
            constraints.add(new LinearConstraint(sumCoefficients, Relationship.LEQ, maxDemand[j]));
        }

        // 求解线性规划问题
        SimplexSolver solver = new SimplexSolver(1e-6);
        PointValuePair solution = solver.optimize(new MaxIter(1000), objectiveFunction, new LinearConstraintSet(constraints), GoalType.MINIMIZE, new NonNegativeConstraint(true));

        // 解析结果
        double totalCost = solution.getValue();
        double[] solutionVector = solution.getPoint();


        // 构建Tcon和Tadv矩阵
        int[][] Tcon = new int[numEnterprises][numMonths];
        int[][] Tadv = new int[numEnterprises][numMonths];
        idx = 0;
        for (int i = 0; i < numEnterprises; i++) {
            for (int j = 0; j < numMonths; j++) {
                Tcon[i][j] = (int) Math.round(solutionVector[idx++]);
                Tadv[i][j] = (int) Math.round(solutionVector[idx++]);
            }
        }

        // 构建Reccon和Recsto
        int[][] Reccon = new int[numEnterprises][numMonths];
        double[] Recsto = new double[numMonths];

        for (int j = 0; j < numMonths; j++) {
            double recstoSum = 0.0;
            for (int i = 0; i < numEnterprises; i++) {
                if (j > 0) {
                    Reccon[i][j] = Reccon[i][j - 1] + Tadv[i][j - 1];  // 递归消耗
                } else {
                    Reccon[i][j] = 0;
                }
                recstoSum += Tadv[i][j] - Reccon[i][j];  // 尚未消耗的提前分配
            }
            Recsto[j] = recstoSum * storageCost;  // 存储成本
        }

        // 修正目标函数，将存储成本加到总成本上
        for (int j = 0; j < numMonths; j++) {
            totalCost += Recsto[j];
        }

        // 构建最终的分配矩阵 T[i,j] = Tcon[i,j] + Tadv[i,j]
        int[][] totalAllocationMatrix = new int[numEnterprises][numMonths];
        for (int i = 0; i < numEnterprises; i++) {
            for (int j = 0; j < numMonths; j++) {
                totalAllocationMatrix[i][j] = Tcon[i][j] + Tadv[i][j];  // 计算总分配量
            }
        }

        // 构建 AssignmentResults 中的 assignmentDetails 数据结构
        Map<String, Map<String, List<Integer>>> assignmentDetails = new HashMap<>();
        for (int i = 0; i < numEnterprises; i++) {
            String enterprise = productEnterprises.get(i);  // 获取企业名称
            List<Integer> allocations = new ArrayList<>();
            for (int j = 0; j < numMonths; j++) {
                allocations.add(totalAllocationMatrix[i][j]);  // 保存该企业每个月的总分配量
            }
            // 将分配数据放入 assignmentDetails，按产品和企业维度组织
            assignmentDetails.computeIfAbsent(product, k -> new HashMap<>()).put(enterprise, allocations);
        }

        // 创建 AssignmentResults 对象并设置结果
        AssignmentResults result = new AssignmentResults();
        result.setScores(totalCost);  // 设置总成本，包括存储成本
        result.setAssignmentDetails(assignmentDetails);  // 设置分配详情，保存总分配矩阵 T[i,j]

        return result;
    }

}

